/***********************************************************************************
 * 文件名： mcu_uart.c
 * 作者： 刘言
 * 版本： 1
 * 说明：
 *      UART驱动。设计思想：面向对象，MCU应用场景几乎不可能中途添加UART，因此静态定义了所有
 *  的UART端口，不过缓存可以配置是静态定义还是动态创建。
 *      中断入口统一定义在 isr.c 中，需要在中断中调用 Uart_EvSendComplete 和 
 *  Uart_EvReceivedByte 并做好标志位清除。
 * ---------------------------------------------------------------------------------
    void Uart_EvSendComplete(uart_t *this);
    void Uart_EvReceivedByte(uart_t *this);

    void USART1_IRQHandler(void)
    {
        if (__HAL_UART_GET_FLAG(&(_UART_USART1_NAME.Handle), UART_FLAG_RXNE) != RESET)   // 收到1个字节
        {
            Uart_EvReceivedByte(&_UART_USART1_NAME);
        }
        if (__HAL_UART_GET_FLAG(&(_UART_USART1_NAME.Handle), UART_FLAG_TC) != RESET)    // 发送完毕1个字节
        {
            __HAL_UART_CLEAR_FLAG(&(_UART_USART1_NAME.Handle), UART_FLAG_TC);
            Uart_EvSendComplete(&_UART_USART1_NAME);
        }
    }
    --------------------------------------------------------------------------------------
 *      在中断入口函数处直接调用各个模块事件通知函数，但必须先调用驱动事件通知函数便于先缓存
 *  数据。
 * 修改记录：
 * 	2023/4/21: 初版。 刘言。
***********************************************************************************/
#include "mcu_uart.h"

#if _UART_BUFF_MODE == 0
// 静态定义 USART1
    #ifdef _UART_USE_USART1
        #if _UART_USART1_TX_BUFF_SIZE
static u8 mUart1TxBuff[_UART_USART1_TX_BUFF_SIZE];
static SoftFifo mUart1TxFifo;
        #endif
        #if _UART_USART1_RX_BUFF_SIZE
static u8 mUart1RxBuff[_UART_USART1_RX_BUFF_SIZE];
static SoftFifo mUart1RxFifo;
        #endif
uart_t _UART_USART1_NAME = {
        #if _UART_USART1_TX_BUFF_SIZE
    mUart1TxBuff, &mUart1TxFifo,
        #else
    NULL, NULL,
        #endif
        #if _UART_USART1_RX_BUFF_SIZE
    mUart1RxBuff, &mUart1RxFifo,
        #else
    NULL, NULL,
        #endif
    _UART_USART1_TX_BUFF_SIZE, _UART_USART1_RX_BUFF_SIZE, false, true, {USART1}};
    #endif
// 静态定义 USART2
    #ifdef _UART_USE_USART2
        #if _UART_USART2_TX_BUFF_SIZE
static u8 mUart2TxBuff[_UART_USART2_TX_BUFF_SIZE];
static SoftFifo mUart2TxFifo;
        #endif
        #if _UART_USART2_RX_BUFF_SIZE
static u8 mUart2RxBuff[_UART_USART2_RX_BUFF_SIZE];
static SoftFifo mUart2RxFifo;
        #endif
uart_t _UART_USART2_NAME = {
        #if _UART_USART2_TX_BUFF_SIZE
    mUart2TxBuff, &mUart2TxFifo,
        #else
    NULL, NULL,
        #endif
        #if _UART_USART2_RX_BUFF_SIZE
    mUart2RxBuff, &mUart2RxFifo,
        #else
    NULL, NULL,
        #endif
    _UART_USART2_TX_BUFF_SIZE, _UART_USART2_RX_BUFF_SIZE, false, true, {USART2}};
    #endif
// 静态定义 USART3
    #ifdef _UART_USE_USART3
        #if _UART_USART3_TX_BUFF_SIZE
static u8 mUart3TxBuff[_UART_USART3_TX_BUFF_SIZE];
static SoftFifo mUart3TxFifo;
        #endif
        #if _UART_USART3_RX_BUFF_SIZE
static u8 mUart3RxBuff[_UART_USART3_RX_BUFF_SIZE];
static SoftFifo mUart3RxFifo;
        #endif
uart_t _UART_USART3_NAME = {
        #if _UART_USART3_TX_BUFF_SIZE
    mUart3TxBuff, &mUart3TxFifo,
        #else
    NULL, NULL,
        #endif
        #if _UART_USART3_RX_BUFF_SIZE
    mUart3RxBuff, &mUart3RxFifo,
        #else
    NULL, NULL,
        #endif
    _UART_USART3_TX_BUFF_SIZE, _UART_USART3_RX_BUFF_SIZE, false, true, {USART3}};
    #endif
// 静态定义 USART4
    #ifdef _UART_USE_USART4
        #if _UART_USART4_TX_BUFF_SIZE
static u8 mUart4TxBuff[_UART_USART4_TX_BUFF_SIZE];
static SoftFifo mUart4TxFifo;
        #endif
        #if _UART_USART4_RX_BUFF_SIZE
static u8 mUart4RxBuff[_UART_USART4_RX_BUFF_SIZE];
static SoftFifo mUart4RxFifo;
        #endif
uart_t _UART_USART4_NAME = {
        #if _UART_USART4_TX_BUFF_SIZE
    mUart4TxBuff, &mUart4TxFifo,
        #else
    NULL, NULL,
        #endif
        #if _UART_USART4_RX_BUFF_SIZE
    mUart4RxBuff, &mUart4RxFifo,
        #else
    NULL, NULL,
        #endif
    _UART_USART4_TX_BUFF_SIZE, _UART_USART4_RX_BUFF_SIZE, false, true, {USART4}};
    #endif
// 静态定义 USART5
    #ifdef _UART_USE_USART5
        #if _UART_USART5_TX_BUFF_SIZE
static u8 mUart5TxBuff[_UART_USART5_TX_BUFF_SIZE];
static SoftFifo mUart5TxFifo;
        #endif
        #if _UART_USART5_RX_BUFF_SIZE
static u8 mUart5RxBuff[_UART_USART5_RX_BUFF_SIZE];
static SoftFifo mUart5RxFifo;
        #endif
uart_t _UART_USART5_NAME = {
        #if _UART_USART5_TX_BUFF_SIZE
    mUart5TxBuff, &mUart5TxFifo,
        #else
    NULL, NULL,
        #endif
        #if _UART_USART5_RX_BUFF_SIZE
    mUart5RxBuff, &mUart5RxFifo,
        #else
    NULL, NULL,
        #endif
    _UART_USART5_TX_BUFF_SIZE, _UART_USART5_RX_BUFF_SIZE, false, true, {USART5}};
    #endif
// 静态定义 USART6
    #ifdef _UART_USE_USART6
        #if _UART_USART6_TX_BUFF_SIZE
static u8 mUart6TxBuff[_UART_USART6_TX_BUFF_SIZE];
static SoftFifo mUart6TxFifo;
        #endif
        #if _UART_USART6_RX_BUFF_SIZE
static u8 mUart6RxBuff[_UART_USART6_RX_BUFF_SIZE];
static SoftFifo mUart6RxFifo;
        #endif
uart_t _UART_USART6_NAME = {
        #if _UART_USART6_TX_BUFF_SIZE
    mUart6TxBuff, &mUart6TxFifo,
        #else
    NULL, NULL,
        #endif
        #if _UART_USART6_RX_BUFF_SIZE
    mUart6RxBuff, &mUart6RxFifo,
        #else
    NULL, NULL,
        #endif
    _UART_USART6_TX_BUFF_SIZE, _UART_USART6_RX_BUFF_SIZE, false, true, {USART6}};
    #endif
// 静态定义 USART7
    #ifdef _UART_USE_USART7
        #if _UART_USART7_TX_BUFF_SIZE
static u8 mUart7TxBuff[_UART_USART7_TX_BUFF_SIZE];
static SoftFifo mUart7TxFifo;
        #endif
        #if _UART_USART7_RX_BUFF_SIZE
static u8 mUart7RxBuff[_UART_USART7_RX_BUFF_SIZE];
static SoftFifo mUart7RxFifo;
        #endif
uart_t _UART_USART7_NAME = {
        #if _UART_USART7_TX_BUFF_SIZE
    mUart7TxBuff, &mUart7TxFifo,
        #else
    NULL, NULL,
        #endif
        #if _UART_USART7_RX_BUFF_SIZE
    mUart7RxBuff, &mUart7RxFifo,
        #else
    NULL, NULL,
        #endif
    _UART_USART7_TX_BUFF_SIZE, _UART_USART7_RX_BUFF_SIZE, false, true, {USART7}};
    #endif
#else
    #error "Not supported."
#endif

#if _UART_BLOCKING_MODE == 0 || _UART_BLOCKING_MODE == 2 || _UART_BLOCKING_MODE == 3 || _UART_BLOCKING_MODE == 4
    #error "Not supported."
#endif


#if HAL_USP_MCU_SERIES == STM32L4XX || HAL_USP_MCU_SERIES == STM32F7XX || HAL_USP_MCU_SERIES == STM32F0XX\
    || HAL_USP_MCU_SERIES == STM32L0XX || HAL_USP_MCU_SERIES == STM32G0XX || HAL_USP_MCU_SERIES == STM32H7XX
    #define _Uart_SendByte(Instance, b) Instance->TDR = b
    #define _Uart_GetRecivedbyte(Instance)  Instance->RDR
#else
    #define _Uart_SendByte(Instance, b) Instance->DR = b
    #define _Uart_GetRecivedbyte(Instance)  Instance->DR
#endif


/**
 * 中断事件：一个字节发送完毕
*/
void Uart_EvSendComplete(uart_t *this)
{
    if(this->TxFifo)
    {
        if(SoftFifo_IsEmpty(this->TxFifo))  // 缓存为空， 说明发送任务完毕了
        {
            this->Sending = false;
        }
        else // 还有数据需要发送
        {
            _Uart_SendByte(this->Handle.Instance, SoftFifo_Read(this->TxFifo));
        }
    }
}

/**
 * 中断事件：一个字节接收完毕(收到一个字节)
*/
void Uart_EvReceivedByte(uart_t *this)
{
    if(this->RxFifo)
    {
        bool ret = SoftFifo_Write(this->RxFifo, _Uart_GetRecivedbyte(this->Handle.Instance));
        if(ret == false)
        {
            // while(1);   // 缓存溢出了
        }
    }
}

void Uart_Init(uart_t *this, u32 baud)
{
    UART_HandleTypeDef huart;

    memset(&huart, 0, sizeof(huart));
    huart.Instance = this->Handle.Instance;
    huart.Init.BaudRate = baud;
    huart.Init.WordLength = UART_WORDLENGTH_8B;
    huart.Init.StopBits = UART_STOPBITS_1;
    huart.Init.Parity = UART_PARITY_NONE;
    huart.Init.Mode = UART_MODE_TX_RX;
    huart.Init.HwFlowCtl = UART_HWCONTROL_NONE;
    huart.Init.OverSampling = UART_OVERSAMPLING_16;
    // huart.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
    huart.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
    if (HAL_UART_Init(&huart) != HAL_OK)
    {
        Error_Handler();
    }
    /* Enable USARTx Receive and Transmit interrupts */
    __HAL_UART_ENABLE_IT(&huart, UART_IT_RXNE);
    __HAL_UART_ENABLE_IT(&huart, UART_IT_TC);

    if(this->TxFifo)SoftFifo_Init(this->TxFifo, this->TxBuff, this->TxBuffSize);
    if(this->RxFifo)SoftFifo_Init(this->RxFifo, this->RxBuff, this->RxBuffSize);
}

void Uart_WriteByte(uart_t *this, u8 c)
{
    if(this->TxFifo)
    {
        bool ret = false;
        while(ret == false) // 死等直到写入缓存成功
        {
            __HAL_UART_DISABLE_IT(&(this->Handle), UART_IT_TC);// 禁止发送完成中断，确保不会在中断中同时操作SoftFifo
            ret = SoftFifo_Write(this->TxFifo, c);
            __HAL_UART_ENABLE_IT(&(this->Handle), UART_IT_TC);// 允许发送完成中断
        }
        if(this->Sending == false)      // 不在发送中，需要启动发送
        {
            this->Sending = true;
            _Uart_SendByte(this->Handle.Instance, SoftFifo_Read(this->TxFifo));// 启动发送
        }
    }
    else
    {
        _Uart_SendByte(this->Handle.Instance, c);// 启动发送
        while (__HAL_UART_GET_FLAG(&(this->Handle), UART_FLAG_TXE) == RESET);
    }
}

void Uart_Write(uart_t *this, const u8 *dat, size_t size)
{
    while(size--)
	{
		Uart_WriteByte(this, *dat);
		dat++;
	}
}

int Uart_ReadByte(uart_t *this)
{
    if(this->RxFifo)
    {
        int ret;
        __HAL_UART_DISABLE_IT(&(this->Handle), UART_IT_RXNE);   // 禁止收到数据中断，确保不会在中断中同时操作SoftFifo
        if(SoftFifo_IsEmpty(this->RxFifo))ret = -1;
        else ret = SoftFifo_Read(this->RxFifo);
        __HAL_UART_ENABLE_IT(&(this->Handle), UART_IT_RXNE);    // 允许收到数据中断
        return ret;
    }
    else    // 没有接收缓存直接返回接收寄存器值
    {
        return _Uart_GetRecivedbyte(this->Handle.Instance);//USART_ReceiveData(this->UartInstance);
    }
}

int Uart_Read(uart_t *this, u8 *buff, size_t cont)
{
    int read_len = 0;
    if(this->RxFifo)
    {
        while(cont--)
        {
            int ret = Uart_ReadByte(this);
            if(ret == -1) break;
            else buff[read_len] = (u8)ret;
            read_len++;
        }
        return read_len;
    }
    else
    {
        return 0;
    }
}

void Uart_SetBaud(uart_t *this, u32 baud)
{
    Uart_Init(this, baud);
}

